#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <hwicodec_common.h>
#include <soc/soc_t21/jzm_i264_enc.h>
#ifdef DMALLOC
#include <imp/dmalloc.h>
#endif
//#include "dump.c"
//extern void dump_t21_sliceinfo(_H264E_SliceInfo *sliceinfo);
//static int ref_mad_bu[100] = {0};
//extern void ncu_reg_dump(ncu_param_t *n);
//struct timeval enctimestart,enctimeend;
/*static int read_ref_mad_bu(hwicodec_t *h,int write_offset,int read_offset,int len)
{
    int i = 0;
    struct reg_info reg_info;
    for (i = 0; i < len; i++) {
        reg_info.paddr = VPU_BASE + write_offset;
        reg_info.value = i;
        reg_info.dir = WRITE_DIR;
        if (ioctl(h->soc.fd, IOCTL_CHANNEL_WOR_VPU_REG, &reg_info)) {
            hwicodec_log(h, C_LOG_WARNING, "%s:write %x failed\n", __func__, reg_info.paddr);
            return -1;
        }
        reg_info.paddr = VPU_BASE + read_offset;
        reg_info.dir = READ_DIR;
        reg_info.value = 0;
        if (ioctl(h->soc.fd, IOCTL_CHANNEL_WOR_VPU_REG, &reg_info)) {
            hwicodec_log(h, C_LOG_WARNING, "%s:read %x failed\n", __func__, reg_info.paddr);
            return -1;
        }
        ref_mad_bu[i] = reg_info.value;
    }

    return 0;
}*/
static int hwicodec_pf_h264e_t21_validate_parameters(hwicodec_t *h)
{
    hwicodec_h264e_param_t *param = &h->param.param.h264e_param;
    if (param->i_threads < 1 || param->i_threads > C_CHN_NUM_MAX) {
        hwicodec_log(h, C_LOG_ERROR, "i_threads:%d is invalidate\n", param->i_threads);
        goto err_i_threads;
    }

    if (param->i_devid > (T21_VPU_NUM - 1)) {
        hwicodec_log(h, C_LOG_ERROR, "i_devid:%d is invalidate\n", param->i_devid);
        goto err_i_devid;
    }

    if (param->i_csp != C_CSP_NV12 && param->i_csp != C_CSP_T420) {
        hwicodec_log(h, C_LOG_ERROR, "i_csp:%d is invalidate\n", param->i_csp);
        goto err_i_csp;
    }

    if (param->i_mb_width < HWICODEC_MIN_MB_WIDTH || param->i_mb_height < HWICODEC_MIN_MB_HEIGHT) {
        hwicodec_log(h, C_LOG_ERROR, "i_mb_resolution:%dx%d is invalidate\n",
                     param->i_mb_width, param->i_mb_height);
        goto err_i_resolution;
    }

    if (!param->scaling_list) {
        hwicodec_log(h, C_LOG_ERROR, "scaling_list is NULL\n", param->scaling_list);
        goto err_scaling_list;
    }

    return 0;

    err_scaling_list:
    err_i_resolution:
    err_i_csp:
    err_i_devid:
    err_i_threads:
    return -1;
}

static int hwicodec_pf_h264e_t21_init(hwicodec_t *h)
{
    int i = 0;
    hwicodec_h264e_param_t *param = &h->param.param.h264e_param;
    hwicodec_vbinfo_t *dmavbinfo = NULL;
    struct channel_node cnode;
    param->H264E_SliceInfoSize = sizeof(_H264E_SliceInfo);
    hwicodec_soc_binfo_t binfo[] = {
        /* referrece && deblock */
        {256,	0,	0,	0,	0,	16,	0,	0,	0},
        /* fenc */
        {256,	0,	0,	0,	16,	16,	0,	0,	0},
        /* bit stream */
        {256,	0,	0,	0,	0,	0,	0,	0,		0},
        /* vconfig dma */
        {128,	0,	0,	0,	0,	0,	0,	0,		0x100000},
        /* ext referrece */
        {4096,	0,	16,	16,	16,	16,	0,	0,	0},
        /* y ncu */
        {16,		0,	0,	0,	0,	0,	0,	0,	1},
		/* rds */
		{256,   0,  0, 0, 256, 16, 0, 0,    0 },
    };

    if ((h->soc.fd = open(SOC_VPU_NAME, O_RDWR | O_SYNC)) < 0) {
        hwicodec_log(h, C_LOG_ERROR, "open %s failed\n", SOC_VPU_NAME);
        goto err_open_soc_vpu_name;
    }

    h->soc.vpu_num = T21_VPU_NUM;
    h->soc.cnpool.cn_num = param->i_threads;

    memset(&cnode, 0, sizeof(struct channel_node));
    cnode.mdelay = MDELAY_TIME;
    cnode.codecdir = HWH264ENC;
    cnode.workphase = OPEN;
    cnode.thread_id = UNUSED_TID;
    if (ioctl(h->soc.fd, IOCTL_CHANNEL_REQ, &cnode) < 0) {
        hwicodec_log(h, C_LOG_ERROR, "request channel failed\n");
        goto err_request_channel;
    }
    for (i = 0; i < h->soc.cnpool.cn_num; i++) {
        h->soc.cnpool.chn[i].cnode = cnode;
        if ((h->soc.cnpool.chn[i].p = malloc(sizeof(_H264E_SliceInfo))) == NULL) {
            hwicodec_log(h, C_LOG_ERROR, "malloc the %d _H264E_SliceInfo failed\n", i);
            goto err_malloc_sliceinfo;
        }
    }

    for (i = 0; i < h->soc.cnpool.cn_num; i++) {
        h->soc.cnpool.chn[i].cnode = cnode;
    }

    if (hwicodec_pf_h264e_init_bpool(h, binfo) < 0) {
        hwicodec_log(h, C_LOG_ERROR, "init bpool failed\n");
        goto err_init_bpool;
    }

    if (h->param.param.h264e_param.b_tlb) {
        if (hwicodec_tlb(h, h->soc.bpool.buf_base_v, h->soc.bpool.buf_size, 0) < 0) {
            hwicodec_log(h, C_LOG_ERROR, "hwicodec tlb failed\n");
            goto err_hwicodec_tlb;
        }
        for (i = 0; i < h->soc.bpool.buf_num; i++) {
            h->soc.bpool.binfo[i].tlb_maped = 1;
        }
        if (h->param.param.h264e_param.empty) {
            if (hwicodec_tlb(h, (intptr_t)h->param.param.h264e_param.empty, h->param.param.h264e_param.i_mb_width*h->param.param.h264e_param.i_mb_height*128, 0) < 0) {
                hwicodec_log(h, C_LOG_ERROR, "hwicodec tlb failed\n");
                goto err_hwicodec_tlb;
            }
        }
    }
    dmavbinfo = &h->soc.bpool.vbinfo[C_SOC_VB_DMA];
    if (dmavbinfo->num != h->param.param.h264e_param.i_threads) {
        hwicodec_log(h, C_LOG_ERROR, "request dma_num:%d, but alloc:%d\n",
                     h->param.param.h264e_param.i_threads, dmavbinfo->num);
        goto err_dma_num;
    }
    for (i = 0; i < dmavbinfo->num; i++) {
        h->soc.cnpool.chn[i].cnode.dma_addr = param->b_tlb ? dmavbinfo->vb[i].yptr
        : h->param.ckvirt_to_phys(dmavbinfo->vb[i].yptr);
    }
    if ((h->soc.vpu_num > 1) && (param->i_devid < 0) && (h->soc.cnpool.cn_num > 1)) {
        if ((h->p = malloc(sizeof(id_pos_t))) == NULL) {
            hwicodec_log(h, C_LOG_ERROR, "malloc id_pos failed\n");
            goto err_malloc_id_pos;
        }
        if (init_id_pos(h->p, param->gopsize, 0, h->soc.vpu_num - 1, param->daisy_chain_en) < 0) {
            hwicodec_log(h, C_LOG_ERROR, "init_id_pos failed\n");
            goto err_init_id_pos;
        }
    }

    /* Private tlb */
    if(h->param.param.h264e_param.private_tlb_flag) {
        if(private_tlb_open(h, 0, h->param.param.h264e_param.private_tlb_vbase,
                            h->param.param.h264e_param.private_tlb_pbase)) {
                                hwicodec_log(h, C_LOG_ERROR, "private tlb open error\n");
                                goto err_init_id_pos;
                            }
    }

    if ((h->param.param.h264e_param.watermark_en) && ((h->wmhandler = watermark_init()) == NULL)) {
        hwicodec_log(h, C_LOG_ERROR, "watermark_init failed\n");
        goto err_watermark_init;
    }

    return 0;

err_watermark_init:
    if (h->param.param.h264e_param.private_tlb_flag) {
        private_tlb_close(h, 0);
    }
    err_init_id_pos:
        free(h->p);
        err_malloc_id_pos:
            err_dma_num:
                err_hwicodec_tlb:
                    hwicodec_pf_deinit_bpool(h);
                    err_init_bpool:
                        i = h->soc.cnpool.cn_num;
                        err_malloc_sliceinfo:
                            for (--i; i >= 0; i--) {
                                free(h->soc.cnpool.chn[i].p);
                                h->soc.cnpool.chn[i].p = NULL;
                            }
                            cnode.workphase = CLOSE;
                            ioctl(h->soc.fd, IOCTL_CHANNEL_REL, &cnode);
                            err_request_channel:
                                close(h->soc.fd);
                                err_open_soc_vpu_name:
                                    return -1;
}

static void hwicodec_pf_h264e_t21_deinit(hwicodec_t *h)
{
    int i = 0;
    hwicodec_h264e_param_t *param = &h->param.param.h264e_param;

    if (h->wmhandler != NULL) {
        watermark_deinit(h->wmhandler);
    }

    /* Private tlb */
    if(h->param.param.h264e_param.private_tlb_flag) {
        if(private_tlb_close(h, 0)) {
            hwicodec_log(h, C_LOG_ERROR, "private tlb close error\n");
            return;
        }
    }

    if ((h->soc.vpu_num > 1) && (param->i_devid < 0) && (h->p) && (h->soc.cnpool.cn_num > 1)) {
        deinit_id_pos(h->p);
        free(h->p);
    }
    hwicodec_pf_deinit_bpool(h);
    for (i = h->soc.cnpool.cn_num - 1; i >= 0; i--) {
        if (h->soc.cnpool.chn[i].p) {
            free(h->soc.cnpool.chn[i].p);
            h->soc.cnpool.chn[i].p = NULL;
        }
    }
    for (i = h->soc.cnpool.cn_num - 1; i >= 0; i--) {
        if (h->soc.cnpool.chn[i].c) {
            free(h->soc.cnpool.chn[i].c);
            h->soc.cnpool.chn[i].c = NULL;
        }
    }
    h->soc.cnpool.chn[0].cnode.workphase = CLOSE;
    ioctl(h->soc.fd, IOCTL_CHANNEL_REL, &h->soc.cnpool.chn[0].cnode);
    close(h->soc.fd);
}

#if 0
static uint32_t hwicodec_pf_h264e_t21_get_ssd(hwicodec_t *h, hwicodec_chn_t *c)
{
    struct reg_info reg_efe_ssad = {
        /*
        * although t21 has two vpu unit helix and radix, but for h264, it has one vpu unit helix, and VPU_BASE is helix
        * base, so vpu_id force to zero when RANDOM_ID appear is also has no problem
        * here is importent to you to transplant to other soc which has many vpu unit, you should be careful
        */
        .paddr = VPU_BASE+((c->cnode.vpu_id == RANDOM_ID ? 0 : (c->cnode.vpu_id & ~VPU_HELIX_ID)) *VPU_DISTANCE)+REG_EFE_SSAD,
        .value = 0,
        .dir = READ_DIR,
    };

    if (ioctl(h->soc.fd, IOCTL_CHANNEL_WOR_VPU_REG, &reg_efe_ssad)) {
        hwicodec_log(h, C_LOG_ERROR, "read REG_EFE_SSAD(%x) failed%d\n", reg_efe_ssad.paddr);
        return 0;
    }

    return reg_efe_ssad.value;
}
#endif

static int hwicodec_pf_h264e_t21_set_priv(hwicodec_t *h, void *priv, int priv_size)
{
    unsigned int *ctx = priv;
    int ctx_cnt = priv_size / (sizeof(unsigned int) * 2);
    int i = 0;
    struct reg_info reg_info;
    for (i = 0; i < ctx_cnt; i++) {
        reg_info.paddr = VPU_BASE + ctx[i * 2];
        reg_info.value = 0;
        reg_info.dir = READ_DIR;
        if (ioctl(h->soc.fd, IOCTL_CHANNEL_WOR_VPU_REG, &reg_info)) {
            hwicodec_log(h, C_LOG_WARNING, "%s:read %x failed\n", __func__, reg_info.paddr);
            return -1;
        }
        ctx[i * 2 + 1] = reg_info.value;
    }

    return 0;
}

extern uint64_t timestamp_ivdc_vpu;
extern unsigned int overflow_cnt_vpu;
extern unsigned int data_threshold_vpu;
extern unsigned int ivdc_mem_line_vpu;
static int hwicodec_pf_h264e_t21_enc(hwicodec_t *h, hwicodec_io_t *input)
{
    int ret;
    hwicodec_h264e_param_t *param = &h->param.param.h264e_param;
    hwicodec_io_h264e_t *io = &input->protocol.h264e;
    hwicodec_chn_t *c = &h->soc.cnpool.chn[io->i_frame % h->soc.cnpool.cn_num];
    _H264E_SliceInfo *s = c->p;
    _H264E_SliceInfo *io_si = (_H264E_SliceInfo*)io->H264E_SliceInfo;

    memset(s, 0, sizeof(_H264E_SliceInfo));
    memcpy(s, io_si, sizeof(_H264E_SliceInfo));

    s->raw_format = convert_csp_to_vpu_mode(io->i_csp);
    if (s->raw_format == HWICODEC_UNSUPPORT_MODE) {
        hwicodec_log(h, C_LOG_ERROR, "unsupported format to convert:%d\n", io->i_csp);
        goto err_unsupport_i_csp;
    }
    s->des_va = (uint32_t *)h->soc.bpool.vbinfo[C_SOC_VB_DMA].vb[io->i_frame % h->soc.cnpool.cn_num].yptr;
    s->des_pa =(uint32_t)(param->b_tlb ? s->des_va : (uint32_t *)h->param.ckvirt_to_phys((intptr_t)s->des_va));
    s->bs = param->b_tlb ? (intptr_t)io->fbs : h->param.ckvirt_to_phys((intptr_t)io->fbs);
    s->emc_bs_pa = param->b_tlb ? (intptr_t)io->fbs : h->param.ckvirt_to_phys((intptr_t)io->fbs);
    s->fb[0][0] = param->b_tlb ? io->fdec.yaddr : h->param.ckvirt_to_phys(io->fdec.yaddr);
    s->fb[0][1] = param->b_tlb ? io->fdec.caddr : h->param.ckvirt_to_phys(io->fdec.caddr);

    if (!io->i_type) {
        s->fb[1][0] = 0;
        s->fb[1][1] = 0;
    } else {
        s->fb[1][0] = param->b_tlb ? io->fref.yaddr : h->param.ckvirt_to_phys(io->fref.yaddr);
        s->fb[1][1] = param->b_tlb ? io->fref.caddr : h->param.ckvirt_to_phys(io->fref.caddr);
		if (param->b_mref && io->mref_en) {
			s->mref_en = 1;
			s->fb[2][0] = param->b_tlb ? io->fref.yaddr : h->param.ckvirt_to_phys(io->fmref.yaddr);
			s->fb[2][1] = param->b_tlb ? io->fref.caddr : h->param.ckvirt_to_phys(io->fmref.caddr);
		}
    }

	s->frame_idx = io->frame_idx;
	if (param->b_buf_share && io->buf_share_en) {
		s->buf_share_en = 1;
		s->buf_share_size = 3;
	}

    /* Private tlb */
    if((param->private_tlb_flag) && (!(io->fenc.yaddr & (1 << 31)))) {
        paddr_t tmp_yaddr;
        tmp_yaddr = io->fenc.yaddr;

        int width = io->i_mb_width*16;
        int height = io->i_mb_height*16;


        private_tlb_map(tmp_yaddr,
                        h->param.ckvirt_to_phys(io->fenc.yaddr),
                        width*height/2, 0);

        private_tlb_map(tmp_yaddr+width*height/2,
                        h->param.ckvirt_to_phys(io->fpad.yaddr),
                        width*height/2, 1);

        private_tlb_map(tmp_yaddr+width*height,
                        h->param.ckvirt_to_phys(io->fenc.caddr),
                        width*height/4, 1);

        private_tlb_map(tmp_yaddr+width*height*5/4,
                        h->param.ckvirt_to_phys(io->fpad.caddr),
                        width*height/4, 1);

        s->raw[0] =  tmp_yaddr;
        s->raw[1] =  tmp_yaddr + width*height;
    } else {
		if (io->fenc.yaddr & (1 << 31)) {
			s->raw[0] = (uint8_t *)(io->fenc.yaddr);
			s->raw[1] = (uint8_t *)(io->fenc.caddr);
		} else {
			if (param->b_use_ncu && io->is_use_ncu) {
				s->raw[0] = 0;//param->b_tlb ? io->fenc.yaddr : h->param.ckvirt_to_phys(io->fenc.yaddr);
				s->raw[1] = param->b_tlb ? io->fenc.caddr : h->param.ckvirt_to_phys(io->fenc.caddr);
			} else {
				s->raw[0] = param->b_tlb ? io->fenc.yaddr : io->fenc.yaddr_pa ? io->fenc.yaddr_pa : h->param.ckvirt_to_phys(io->fenc.yaddr);
				s->raw[1] = param->b_tlb ? io->fenc.caddr : io->fenc.caddr_pa ? io->fenc.caddr_pa : h->param.ckvirt_to_phys(io->fenc.caddr);
			}
		}
    }

    if (param->b_user_fenc && param->b_tlb && (hwicodec_vb_tlb(h, &h->soc.ppool, &io->fenc, &io->fenc_size, 0) < 0)) {
		hwicodec_log(h, C_LOG_ERROR, "hwicodec fenc tlb failed\n");
		goto err_hwicodec_fenc_tlb;
    }

    if (param->b_use_ncu && io->is_use_ncu) {
        s->stride[0] = 0;
		s->stride[1] = io->i_fenc_stride[1];
	} else {
        s->stride[0] = io->i_fenc_stride[0];
		s->stride[1] = io->i_fenc_stride[1];
	}

	if (io->fenc.yaddr & (1 << 31)) {
		s->raw[0] = (uint8_t *)(io->fenc.yaddr);
		s->raw[1] = (uint8_t *)(io->fenc.caddr);
		s->stride[0] = s->stride[1] = 4096;
	} else {
		if (param->b_use_ncu && io->is_use_ncu) {
			s->raw[0] = 0;
			s->raw[1] = s->raw[1]+s->stride[1]*io->start_mb_y*8+io->start_mb_x*16;
		} else {
			s->raw[0] = s->raw[0]+s->stride[0]*io->start_mb_y*16+io->start_mb_x*16;
			s->raw[1] = s->raw[1]+s->stride[1]*io->start_mb_y*8+io->start_mb_x*16;
		}
	}

	s->emc_dblk_pa  = 0;
	s->emc_recon_pa = 0;
	s->emc_mv_pa    = 0;
	s->emc_se_pa    = 0;
	s->emc_qpt_pa = (uint32_t)(param->b_tlb ? s->emc_qpt_va : (uint32_t *)h->param.ckvirt_to_phys((intptr_t)s->emc_qpt_va));
	s->emc_rc_pa  = (uint32_t)(param->b_tlb ? s->emc_rc_va : (uint32_t *)h->param.ckvirt_to_phys((intptr_t)s->emc_rc_va));
	s->emc_cpx_pa = (uint32_t)(param->b_tlb ? s->emc_cpx_va : (uint32_t *)h->param.ckvirt_to_phys((intptr_t)s->emc_cpx_va));
	s->emc_mod_pa = (uint32_t)(param->b_tlb ? s->emc_mod_va : (uint32_t *)h->param.ckvirt_to_phys((intptr_t)s->emc_mod_va));
	s->emc_ncu_pa = (uint32_t)(param->b_tlb ? s->emc_ncu_va : (uint32_t *)h->param.ckvirt_to_phys((intptr_t)s->emc_ncu_va));
	s->emc_sad_pa = (uint32_t)(param->b_tlb ? s->emc_sad_va : (uint32_t *)h->param.ckvirt_to_phys((intptr_t)s->emc_sad_va));

	s->tlba = 0;
	memset(s->jh,0,sizeof(s->jh));
	s->spe_y_addr = 0;
	s->spe_c_addr = 0;

/*
    static  int yuccnt = 0;
    FILE *yuvfile;
    yuccnt++;
    if((yuccnt > 50)&&(yuccnt<81))
    {
        yuvfile = fopen("/tmp/raw_1920x1080.yuv","a");
        if(yuvfile == NULL)
        printf("open raw_1920x1080.yuv error");
        fwrite(io->fenc.yaddr,1920*1080,1,yuvfile);

        fwrite(io->fenc.caddr,1920*1080/2,1,yuvfile);
        fclose(yuvfile);
    }
    */
    s->daisy_chain_en = param->daisy_chain_en;
    s->curr_thread_id = h->soc.cnpool.chn[0].cnode.channel_id;

    if ((!io->i_type) && s->daisy_chain_en) {
        c->cnode.thread_id = s->curr_thread_id;
    } else {
        c->cnode.thread_id = UNUSED_TID;
    }

    if ((h->param.param.h264e_param.watermark_en) && (s->frame_type == 0 /* I frame type*/)) {
        unsigned char *ybuf = (unsigned char *)io->fenc.yaddr;
        if (embed_watermark(h->wmhandler, ybuf, s->mb_width * 16, s->mb_height * 16) < 0) {
            hwicodec_log(h, C_LOG_ERROR, "embed wm failed\n");
            goto err_embed_watermark;
        }
    }
	//dump_t21_sliceinfo(s);
    H264E_T21_SliceInit(s);
#if 0
c->cnode.vpu_id = (param->daisy_chain_en > 0) ? (VPU_HELIX_ID | 1 << (io->i_frame % h->soc.vpu_num))
    : (param->i_devid >= 0 ? (VPU_HELIX_ID | 1 << param->i_devid) : RANDOM_ID);
#else
    c->cnode.vpu_id = VPU_HELIX_ID | 1 << 0;
#endif

#ifdef CONFIG_SINGLE_BS
    hwicodec_bsbuf_lock();
#endif
//    gettimeofday(&enctimestart,NULL);

	if (io->fenc.yaddr & (1 << 31)) {
		c->cnode.frame_type = 3;
		c->cnode.overflow_cnt = overflow_cnt_vpu;
		c->cnode.ivdc_mem_line = ivdc_mem_line_vpu;
		c->cnode.data_threshold = data_threshold_vpu;
		c->cnode.time = timestamp_ivdc_vpu;
	}

	ret = ioctl(h->soc.fd, IOCTL_CHANNEL_RUN, &c->cnode);
	if (ret < 0) {
		hwicodec_log(h, C_LOG_ERROR, "vpu channel run failed\n");
		goto err_vpu_channel_run;
	} else if (ret == 0x2) {
		input->bslen = c->cnode.output_len = 0;
		return 0x2;
	}

	// gettimeofday(&enctimeend,NULL);
	// int timedt = (enctimeend.tv_sec*1000 + enctimeend.tv_usec/1000) -(enctimestart.tv_sec*1000 + enctimestart.tv_usec/1000);
	// printf("encode_h264 time = %d\n",timedt);
	io->cmpx = c->cnode.cmpx;

	hwicodec_pf_h264e_t21_set_priv(h, io->priv, io->priv_size);
/*
	   struct reg_info reg_info;
	   int p;
	   reg_info.paddr = VPU_BASE + 0x50000 ;
	   reg_info.dir = READ_DIR;
	   reg_info.value = 0;
	   if (ioctl(h->soc.fd, IOCTL_CHANNEL_WOR_VPU_REG, &reg_info)) {
	   hwicodec_log(h, C_LOG_WARNING, "%s:read %x failed\n", __func__, reg_info.paddr);
	   return -1;
	   }
	   printf( "0x%x value =0x%x\n",reg_info.paddr,reg_info.value);
*/
	if ((h->soc.vpu_num > 1) && (param->i_devid < 0) && (h->p) && (h->soc.cnpool.cn_num > 1)) {
		release_id(h->p, c->cnode.vpu_id & ~VPU_HELIX_ID);
	}
	input->bslen = c->cnode.output_len;

	return 0;

err_vpu_channel_run:
    if ((h->soc.vpu_num > 1) && (param->i_devid < 0) && (h->p) && (h->soc.cnpool.cn_num > 1)) {
        release_id(h->p, c->cnode.vpu_id & ~VPU_HELIX_ID);
    }
    err_embed_watermark:
        err_hwicodec_fenc_tlb:
            err_unsupport_i_csp:
                return -1;
}


hwicodec_func_t hwicodec_pf_h264e_t21 = {
    .validate_parameters	= hwicodec_pf_h264e_t21_validate_parameters,
    .init					= hwicodec_pf_h264e_t21_init,
    .deinit					= hwicodec_pf_h264e_t21_deinit,
    .process				= hwicodec_pf_h264e_t21_enc,
    .request_vbinfo			= hwicodec_pf_request_vbinfo,
    .release_vbinfo			= hwicodec_pf_release_vbinfo,
};
